<template>
  <div ref="editorContainer" class="editor-container"></div>
</template>

<script setup lang="ts">
  import { Monaco } from './monaco'
  import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue'

  interface EditorProps {
    modelValue?: string
    language?: string
    readOnly?: boolean
  }
  const props = withDefaults(defineProps<EditorProps>(), {
    modelValue: '',
    language: 'javascript',
    readOnly: false
  })

  const emit = defineEmits<{
    (e: 'update:modelValue', newCode: string): void
  }>()

  const editorContainer = ref<HTMLDivElement | null>(null)
  let editorInstance: Monaco.editor.IStandaloneCodeEditor | null = null

  onMounted(() => {
    if (editorContainer.value) {
      editorInstance = Monaco.editor.create(editorContainer.value, {
        value: props.modelValue,
        language: props.language,
        theme: 'custom-dark',
        readOnly: props.readOnly,
        formatOnType: true,  // // 输入时自动格式化
        formatOnPaste: true, // 当粘贴的时候自动进行一次格式化代码
        tabSize: 2, // tab缩进长度
        wordWrap: "bounded",     // 设置为 'bounded' 以启用受限换行
        wordWrapColumn: 100      // 超过100字符自动换行
      })

      editorInstance.onDidChangeModelContent(() => {
        emit('update:modelValue', editorInstance?.getValue() || '')
      })

      formatCode()
    }
  })

  watch(
    () => props.modelValue,
    (newCode) => {
      if (editorInstance && newCode !== editorInstance.getValue()) {
        editorInstance.setValue(newCode)
      }
    },
    { immediate: true }
  )

  watch(
    () => props.readOnly,
    (newVal) => {
      if (editorInstance) {
        editorInstance.updateOptions({ readOnly: newVal })
      }
    }
  )

  // 格式化代码
  const formatCode = () => {
    window.requestIdleCallback(
      async () => {
        if (editorInstance) {
          const readOnly = props.readOnly
          if (readOnly) {
            // 暂时取消只读模式 因为格式化只在编辑模式下有用
            editorInstance.updateOptions({ readOnly: false })
          }
          await editorInstance.getAction('editor.action.formatDocument')?.run()

          if (readOnly) {
            // 恢复只读模式
            editorInstance.updateOptions({ readOnly: true })
          }
        }
      }
    )
  }

  const getNewCode = () => {
    return editorInstance?.getValue() || ''
  }

  defineExpose({
    getNewCode
  })

  onBeforeUnmount(() => {
    if (editorInstance) {
      editorInstance.dispose()
    }
  }) 
</script>

<style lang="less" scoped>
  .editor-container {
    width: 100%;
    height: 100%;
  }
</style>